package com.ruoyi.common.utils;

import com.ruoyi.project.loans.payment.domain.PaymentDetail;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;

/**
 * 还款计划工具类
 */
public class PaymentUtil {

    public static void main(String[] args){
        //
        BigDecimal total = new BigDecimal(Double.toString(60000));
        BigDecimal rate = new BigDecimal(Double.toString(0.00040));
        BigDecimal period = new BigDecimal(Double.toString(12));
        Date date = DateUtils.parseDate("2020-06-15");
//        mayiLend(new BigDecimal(Double.toString(10000)),new BigDecimal(Double.toString(0.0004)),new BigDecimal(Double.toString(12)));
//        debjPayment(total,rate,period);
        xxhbPayment(total,rate,period,DateUtils.parseDate("2020-06-15"),16);
    }

    /**
     * 等额本息
     * @param total 总额
     * @param rate  日利率
     * @param period 期数
     * @param paymentDay 每月还款日期
     */
    public static PaymentDetail[] debxPayment(
            final BigDecimal total,
            BigDecimal rate,
            BigDecimal period,
            Date date,
            Integer paymentDay)
    {
        Calendar[] dates=new Calendar[period.intValue()];
        Calendar now=Calendar.getInstance();
        now.setTime(date);
        setTimeToMidnight(now);
        int now_year = now.get(Calendar.YEAR);
        int now_month = now.get(Calendar.MONTH);
        int year=now_year;
        int month=now_month;
        int day = paymentDay;//每月10号
        PaymentDetail repays[]=new PaymentDetail[period.intValue()];//保存每期还款信息
        for(int i=0;i<period.intValue();i++){
            repays[i]=new PaymentDetail();
            if(++month>11){
                month=0;
                year++;
            }
            Calendar c=Calendar.getInstance();
            setTimeToMidnight(c);
            c.set(Calendar.YEAR, year);
            c.set(Calendar.MONTH, month);
            c.set(Calendar.DAY_OF_MONTH, day);
            dates[i]=c;
        }
        BigDecimal average=total.divide(period,2, BigDecimal.ROUND_DOWN);//平均每月还款，最开始设为贷款总额/期数
        BigDecimal remain=null;//剩余未还的
        BigDecimal step=new BigDecimal(Double.toString(0.01));
        do {
            if(remain!=null) {
                average = average.add(remain.divide(period, 2, BigDecimal.ROUND_DOWN));//平均还款=平均还款(上次)+(剩余(上次)/期数)  保留两位小数点
            }
            remain = total;
            long lastTime = now.getTimeInMillis();
            for (int i = 0; i < period.intValue(); i++) {
                long rePlayTime = dates[i].getTimeInMillis();//还款时间
                BigDecimal days = new BigDecimal(Double.toString(millisecondsToDays(rePlayTime - lastTime)));//计算与上一次还款日间隔(天数)
                BigDecimal interest =days.multiply(rate).multiply(remain).setScale(2,BigDecimal.ROUND_DOWN);//计算当期利息，天数*日利率*剩余未还金额
                BigDecimal principal = average.subtract(interest);
                repays[i].setPaymentTime(dates[i].get(Calendar.YEAR)+"年"
                        +(dates[i].get(Calendar.MONTH)+1)+"月"
                        +dates[i].get(Calendar.DAY_OF_MONTH)+"日");
                repays[i].setPaymentInterest(interest);
                repays[i].setPaymentPrincipal(principal);
                remain=remain.subtract(principal);
                if(i==period.intValue()-1){//最后一次还款加上(或减)余数
                    repays[i].setPaymentPrincipal(repays[i].getPaymentPrincipal().add(remain));
                }
                repays[i].setPaymentAverage(interest.add(repays[i].getPaymentPrincipal()));
                lastTime = rePlayTime;
            }
        }while(remain.abs().compareTo(step.multiply(period))>=0);//如果剩余未还的绝对值大于等于(期数*0.01)，则继续分割

        return  repays;
    }

    static void setTimeToMidnight(Calendar calendar) {//设置每天12点0分0秒为分割点
        calendar.set(Calendar.HOUR_OF_DAY, 12);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
    }

    static int millisecondsToDays(long intervalMs) {//计算天数
        return (int) (intervalMs / (1000 * 86400));
    }



    /**
     * 等额本金
     * @param total      贷款总额
     * @param period         贷款期限
     * @param rate           贷款利率
     * @return
     */
   public static PaymentDetail[] debjPayment(
           final BigDecimal total,
           BigDecimal rate,
           BigDecimal period,
           Date date,
           Integer paymentDay)
   {
       Calendar[] dates=new Calendar[period.intValue()];
       Calendar now=Calendar.getInstance();
       now.setTime(date);
       setTimeToMidnight(now);
       int now_year = now.get(Calendar.YEAR);
       int now_month = now.get(Calendar.MONTH);
       int now_day = now.get(Calendar.DAY_OF_MONTH);
       int year=now_year;
       int month=now_month;
       int day=paymentDay;//每月10号
       PaymentDetail repays[]=new PaymentDetail[period.intValue()];//保存每期还款信息
       for(int i=0;i<period.intValue();i++){
           repays[i]=new PaymentDetail();
           if(++month>11){
               month=0;
               year++;
           }
           Calendar c=Calendar.getInstance();
           setTimeToMidnight(c);
           c.set(Calendar.YEAR, year);
           c.set(Calendar.MONTH, month);
           c.set(Calendar.DAY_OF_MONTH, day);
           dates[i]=c;
       }

       // 1.每次还款的本金
       BigDecimal average=total.divide(period,2, BigDecimal.ROUND_DOWN);

       BigDecimal remain=total;//剩余未还的
       BigDecimal step=new BigDecimal(Double.toString(0.01));

       do {
           long lastTime = now.getTimeInMillis();
           for (int i = 0; i < period.intValue(); i++) {
               long rePlayTime = dates[i].getTimeInMillis();//还款时间
               BigDecimal days = new BigDecimal(Double.toString(millisecondsToDays(rePlayTime - lastTime)));//计算与上一次还款日间隔(天数)
               BigDecimal interest =days.multiply(rate).multiply(remain).setScale(2,BigDecimal.ROUND_DOWN);//计算当期利息，天数*日利率*剩余未还金额

               BigDecimal principal = average;
               repays[i].setPaymentTime(dates[i].get(Calendar.YEAR)+"年"
                       +(dates[i].get(Calendar.MONTH)+1)+"月"
                       +dates[i].get(Calendar.DAY_OF_MONTH)+"日");
               repays[i].setPaymentInterest(interest);
               repays[i].setPaymentPrincipal(principal);
               remain=remain.subtract(principal);
               if(i==period.intValue()-1){//最后一次还款加上(或减)余数
                   repays[i].setPaymentPrincipal(repays[i].getPaymentPrincipal().add(remain));
               }
               repays[i].setPaymentAverage(interest.add(repays[i].getPaymentPrincipal()));
               lastTime = rePlayTime;
           }
       }while(remain.abs().compareTo(step.multiply(period))>=0);//如果剩余未还的绝对值大于等于(期数*0.01)，则继续分割

//       for(int i=0;i<period.intValue();i++){
//           Repayment repay=repays[i];
//           System.out.println("第"+(i+1)+"期  时间："+repay.date.get(Calendar.YEAR)+"年"+(repay.date.get(Calendar.MONTH)+1)+"月"
//                   +repay.date.get(Calendar.DAY_OF_MONTH)+"日 还款:"+repay.payment+" = 本金:"+repays[i].principal +" + 利息:"+repays[i].interest);
//       }
        return repays;
   }


    /**
     * 先息后本
     * @param total      贷款总额
     * @param period         贷款期限
     * @param rate           贷款利率
     * @return
     */
    public static PaymentDetail[] xxhbPayment(
            final BigDecimal total,
            BigDecimal rate,
            BigDecimal period,
            Date date,
            Integer paymentDay)
    {
        Calendar[] dates=new Calendar[period.intValue()];
        Calendar now=Calendar.getInstance();
        now.setTime(date);
        setTimeToMidnight(now);
        int now_year = now.get(Calendar.YEAR);
        int now_month = now.get(Calendar.MONTH);
        int now_day = now.get(Calendar.DAY_OF_MONTH);
        int year=now_year;
        int month=now_month;
        int day=paymentDay;//每月10号
        PaymentDetail repays[]=new PaymentDetail[period.intValue()];//保存每期还款信息
        for(int i=0;i<period.intValue();i++){
            repays[i]=new PaymentDetail();
            if(++month>11){
                month=0;
                year++;
            }
            Calendar c=Calendar.getInstance();
            setTimeToMidnight(c);
            c.set(Calendar.YEAR, year);
            c.set(Calendar.MONTH, month);
            c.set(Calendar.DAY_OF_MONTH, day);
            dates[i]=c;
        }

        BigDecimal remain=total;//剩余未还的
        BigDecimal step=new BigDecimal(Double.toString(0.01));

        do {
            long lastTime = now.getTimeInMillis();
            for (int i = 0; i < period.intValue(); i++) {
                long rePlayTime = dates[i].getTimeInMillis();//还款时间
                BigDecimal days = new BigDecimal(Double.toString(millisecondsToDays(rePlayTime - lastTime)));//计算与上一次还款日间隔(天数)
                BigDecimal interest =days.multiply(rate).multiply(remain).setScale(2,BigDecimal.ROUND_DOWN);//计算当期利息，天数*日利率*剩余未还金额

                repays[i].setPaymentTime(dates[i].get(Calendar.YEAR)+"年"
                        +(dates[i].get(Calendar.MONTH)+1)+"月"
                        +dates[i].get(Calendar.DAY_OF_MONTH)+"日");
                repays[i].setPaymentInterest(interest);
                repays[i].setPaymentPrincipal(new BigDecimal(0));
                if(i==period.intValue()-1){//最后一次还款加上(或减)余数
                    repays[i].setPaymentPrincipal(total);
                    remain = new BigDecimal(0);
                }
                repays[i].setPaymentAverage(interest.add(repays[i].getPaymentPrincipal()));
                lastTime = rePlayTime;
            }
        }while(remain.abs().compareTo(step.multiply(period))>=0);//如果剩余未还的绝对值大于等于(期数*0.01)，则继续分割

        return repays;
   }
}
